# coding=utf8
__author__ = 'lijian'
import logging

import lamp
from protocol.uplink.packet import *
from utils import byteUtil
from utils import bcdUtil
import config
import rtu


def fn_1(dataUnit):
    data = []

    bs = byteUtil.encodeShort(config.uplink["slaveTimeout"])
    bs[1] = bs[1] | (config.uplink["retry"] << 4)

    data.extend(bs)

    con = config.uplink["initiative"]["realTime"]
    con = config.uplink["initiative"]["history"] << 1 | con
    con = config.uplink["initiative"]["event"] << 2 | con

    data.append(con)
    data.append(config.uplink["heartbeatCycle"])
    du = DataUnit(pn=0, fn=1, data=data)
    return du


def fn_2(dataUnit):
    ip = config.network["server"]["ip"]
    port = config.network["server"]["port"]

    data = []
    array = ip.split(".")
    for c in array:
        data.append(int(c))
    data.extend(byteUtil.encodeShort(port))
    apn = config.network["gprs"]["apn"]

    bs = byteUtil.strToBytes(apn, 16)
    data.extend(bs)

    du = DataUnit(pn=0, fn=2, data=data)
    return du


def fn_3(dataUnit):
    data = []

    validity = []
    importance = []
    initiative = []
    for key, value in config.eventConfig.iteritems():
        validity.append(value["validity"])
        importance.append(value["importance"])
        initiative.append(value["initiative"])

    bs = [0] * 8
    index = 0
    for i in range(8):
        for k in range(8):
            value = int(validity[index])
            bs[i] = bs[i] | (value << k)

            index += 1
    data.extend(bs)

    bs = [0] * 8
    index = 0
    for i in range(8):
        for k in range(8):
            value = int(importance[index])
            bs[i] = bs[i] | (value << k)

            index += 1
    data.extend(bs)

    bs = [0] * 8
    index = 0
    for i in range(8):
        for k in range(8):
            value = int(initiative[index])
            bs[i] = bs[i] | (value << k)

            index += 1
    data.extend(bs)

    du = DataUnit(pn=0, fn=3, data=data)
    return du


def fn_4(dataUnit):
    data = []

    data.extend(config.info["boxNo"])
    data.extend(config.info["address"])
    data.extend(bcdUtil.numberToBcd(config.info["longitude"]))
    data.extend(bcdUtil.numberToBcd(config.info["latitude"]))
    data.append(int(config.info["lampEnable"]))
    data.extend(byteUtil.encodeShort(config.info["frequency"]))

    du = DataUnit(pn=0, fn=4, data=data)
    return du


def fn_5(dataUnit):
    data = []

    data.append(config.eventDetectionConfig["commFailTime"])
    data.append(config.eventDetectionConfig["routeFailTime"])
    data.append(config.eventDetectionConfig["lampOnDelay"])
    data.append(config.eventDetectionConfig["lampOffDelay"])
    data.append(config.eventDetectionConfig["lampCurrentDelay"])

    du = DataUnit(pn=0, fn=5, data=data)
    return du


def fn_6(dataUnit):
    data = []

    data.append(int(config.lampThresholdConfig["maxCurrentThreshold"]))
    data.append(int(config.lampThresholdConfig["maxCurrentRecover"]))

    data.append(int(config.lampThresholdConfig["minCurrentThreshold"] * 1000))
    data.append(int(config.lampThresholdConfig["minCurrentRecover"] * 1000))

    value = byteUtil.encodeA5(config.lampThresholdConfig["lowPFThreshold"])
    data.extend(value)

    value = byteUtil.encodeA5(config.lampThresholdConfig["lowPFRecover"])
    data.extend(value)

    data.append(int(config.lampThresholdConfig["breakdownCurrentThreshold"] * 1000))
    data.append(int(config.lampThresholdConfig["breakdownCurrentRecover"] * 1000))
    data.append(int(config.lampThresholdConfig["burnCurrentThreshold"] * 1000))
    data.append(int(config.lampThresholdConfig["burnCurrentRecover"] * 1000))

    du = DataUnit(pn=0, fn=6, data=data)
    return du


def fn_7(dataUnit):
    return False


def fn_9(dataUnit):
    month = dataUnit.rawData[0]
    day = dataUnit.rawData[1]
    count =byteUtil.decodeShort(dataUnit.rawData[2:4])

    data = rtu.action.readTimeSheet(month, day, count)

    if data:
        du = DataUnit(pn=0, fn=9, data=data)
        return du


def fn_11(dataUnit):
    data = []

    bcd = bcdUtil.numberToBcd(config.rtuDetectionInterval["DI"], size=2)
    data.extend(bcd)

    bcd = bcdUtil.numberToBcd(config.rtuDetectionInterval["AI"], 3)
    data.extend(bcd)

    bcd = bcdUtil.numberToBcd(config.rtuDetectionInterval["ammeter"], 2)
    data.extend(bcd)

    du = DataUnit(pn=0, fn=11, data=data)
    return du


def fn_12(dataUnit):
    data = []

    number = 0
    for i in range(len(config.rtuLoopParam["ctrlValid"])):
        v = config.rtuLoopParam["ctrlValid"][i]
        if v:
            number = number | (1 << i)

    data.extend(byteUtil.encodeShort(number))
    data.append(int(config.rtuLoopParam["saving"]))
    data.append(config.rtuLoopParam["level"])

    du = DataUnit(pn=0, fn=12, data=data)
    return du


def fn_13(dataUnit):
    groupNo = dataUnit.PN

    group = lamp.manager.getGroup(groupNo)

    data = []
    data.append(1)  # 启用标志
    data.append(group.autoTasksSize())  # 本次设ra置的控制组数
    for task in group.autoTasks:
        if not task:
            continue
        data.append(task.no)  # 配置回路
        data.append(task.timeType)  # 操作方式
        data.append(task.ctrlType)  # 控制类型
        data.append(task.level)  # 目标状态
        data.append(task.relativeTime)  # 操作相对时间值
        data.extend(bcdUtil.encodeDataTime(task.absoluteTime))  # 操作绝对时间值

    du = DataUnit(pn=dataUnit.PN, fn=19, data=data)
    return du


# 集中器与单灯控制器关系参数设置
def fn_17(dataUnit):
    logging.info("do get term info")
    raw = dataUnit.rawData
    count = raw[0]

    terms = []
    offset = 1
    for i in range(count):
        lampNo = byteUtil.decodeShort(raw[offset:offset + 2])
        offset += 2

        term = lamp.manager.findTermByDeviceId(lampNo)
        if term != None:
            terms.append(term)

    data = [len(terms)]  # 本次下发单灯控制器个数
    for t in terms:
        data.extend(byteUtil.encodeShort(t.deviceId))  # 设备序号
        data.append(t.enable)  # 有效标志

        uid="%d%d%d%d%d%d"%(t.uid[0],t.uid[1],t.uid[2],t.uid[3],t.uid[4],t.uid[5])
        uid = int(uid)

        data.extend(byteUtil.encodeLong(uid) )  # 控制器通信地址
        data.append(t.loopFlag)  # 回路有效标志
        data.extend(byteUtil.encodeInt(t.poleNo))  # 所处杆号

    du = DataUnit(pn=dataUnit.PN, fn=17, data=data)
    return du


# 单灯控制器与灯具关系参数
def fn_18(dataUnit):
    logging.info("do get term & holder info")
    raw = dataUnit.rawData
    count = raw[0]

    term = lamp.manager.findTermByDeviceId(dataUnit.PN)
    if not term:
        data = [0]
        du = DataUnit(pn=dataUnit.PN, fn=18, data=data)
        return du

    holders = []
    offset = 1
    for i in range(count):
        holderNo = byteUtil.decodeShort(raw[offset:offset + 2])
        holder = term.getHolder(holderNo)
        if holder:
            holders.append(holder)
        offset += 2

    data = [len(holders)]  # 本次下发单灯控制器个数
    for holder in holders:
        data.extend(byteUtil.encodeShort(holder.holderNo))  # 灯具序号
        data.append(holder.enable)
        data.append(holder.lineNo)
        data.append(holder.phase)
        data.append(holder.loopNo)

    du = DataUnit(pn=dataUnit.PN, fn=18, data=data)
    return du


# 单灯自动控制参数
def fn_19(dataUnit):
    logging.info("do get lamp auto ctrl info")
    raw = dataUnit.rawData
    holderNo = dataUnit.PN

    term = lamp.manager.findHolder(holderNo)
    if not term:
        data = []
        data.append(1)  # 启用标志
        data.append(0)  # 本次设ra置的控制组数
        du = DataUnit(pn=dataUnit.PN, fn=19, data=data)
        return du

    data = []
    data.append(1)  # 启用标志
    data.append(term.autoTasksSize())  # 本次设ra置的控制组数
    for task in term.autoTasks:
        if not task:
            continue
        data.append(task.no)  # 配置回路
        data.append(task.timeType)  # 操作方式
        data.append(task.ctrlType)  # 控制类型
        data.append(task.level)  # 目标状态
        data.append(task.relativeTime)  # 操作相对时间值
        data.extend(bcdUtil.encodeDataTime(task.absoluteTime))  # 操作绝对时间值

    du = DataUnit(pn=dataUnit.PN, fn=19, data=data)
    return du


def fn_20(dataUnit):
    term = lamp.manager.findTermByDeviceId(dataUnit.PN)
    if not term:
        return False

    groups = term.groups
    data = []
    data.append(len(groups))

    for g in groups:
        data.append(g)

    du = DataUnit(pn=dataUnit.PN, fn=20, data=data)
    return du


def fn_25(dataUnit):
    count = dataUnit.rawData[0]
    start = dataUnit.rawData[1]

    values = rtu.manager.getSignalType(start, count)

    data = []
    data.append(len(values))
    data.append(start)
    for v in values:
        data.append(v["type"])
        data.append(v["line"])
        data.append(v["phase"])

    du = DataUnit(pn=dataUnit.PN, fn=25, data=data)
    return du


def fn_26(dataUnit):
    count = dataUnit.rawData[0]
    start = dataUnit.rawData[1]

    values = rtu.manager.getAnalogLimitParam(start, count)

    point = start
    data = []
    data.append(len(values))
    data.append(start)
    for v in values:
        type = v["type"]
        data.append(v["enable"])
        data.append(v["type"])
        data.append(v["line"])
        data.append(v["phase"])

        data.extend(rtu.manager.encodeAnalog(type, v["onUpperLimit"]))
        data.extend(rtu.manager.encodeAnalog(type, v["onLowerLimit"]))
        data.extend(rtu.manager.encodeAnalog(type, v["offUpperLimit"]))
        data.extend(rtu.manager.encodeAnalog(type, v["offLowerLimit"]))

        point += 1

    du = DataUnit(pn=dataUnit.PN, fn=26, data=data)
    return du
